using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Net;
using interpreter_base.Functions;

namespace interpreter_base
{
    public class Compiler
    {
        public event CompileUnknownScriptLineHandler OnCompileUnknownScriptLine;
        public CompileEnvironment cEnv = new CompileEnvironment();

        public Compiler()
        {

        }
        public void Compile(string[] fileLines)
        {
            for (int i = 0; i < fileLines.Length; i++)
            {
                string line = fileLines[i];
                Escape(ref line);
                string[] spaceSplitArray = getArray(line);
                if (spaceSplitArray.Length == 0) continue;
                BaseInput(spaceSplitArray[0], spaceSplitArray);
            }
        }
        public void CompileLine(string line)
        {
            Escape(ref line);
            string[] spaceSplitArray = getArray(line);
            if (spaceSplitArray.Length == 0) return;
            BaseInput(spaceSplitArray[0], spaceSplitArray);
        }
        void BaseInput(string line, string[] lines)
        {
            try
            {
                switch (line)
                {
                    case "say":
                        BaseOperators.Say(this, lines);
                        break;
                    case "prt":
                        BaseOperators.Prt(this, lines);
                        break;
                    case "def":
                        BaseOperators.def(this, lines);
                        break;
                    case "clr":
                        BaseOperators.Clr(this, lines);
                        break;
                    case "set":
                        BaseOperators.Set(this, lines, line);
                        break;
                    case "exec":
                        BaseOperators.exec(this, lines);
                        break;
                    default:
                        try
                        { onCompileUnknownScriptLine(line, lines); }
                        catch (Exception ex)
                        { PrintError(ex.Message); }
                        break;
                }
            }
            catch
            { PrintError("syntax error."); }
        }
        internal void onCompileUnknownScriptLine(string line, string[] spaceSplitArray)
        {
            if (OnCompileUnknownScriptLine != null) OnCompileUnknownScriptLine(this, line, spaceSplitArray);
        }
        void Escape(ref string line)
        {
            line = line.Replace("\\r", "\r").Replace("\\n", "\n").Replace("\\t", "\t");
        }
        public string[] getArray(string line)
        {
            ArrayList lineArray = new ArrayList();
            string fieldBuff = null;
            bool qmark = false;

            for (int i = 0; i < line.Length; i++)
            {
                string c = line[i].ToString();
                if (i == 0) lineArray = new ArrayList();
                if (fieldBuff == null) fieldBuff = "";
                if (c == "\"") qmark = !qmark;
                //Console.WriteLine ("c=\"" + c + "\" and qmark = \"" + qmark + "\"   ===   " + (c != " ") + " , "+ (c == " " && qmark) +"");
                if (c != " " || (c == " " && qmark))
                {
                    fieldBuff += c;
                    if (i == line.Length - 1)
                    {
                        lineArray.Add(fieldBuff);
                        continue;
                    }
                }
                else
                {
                    //Console.WriteLine ("add " + fieldBuff);
                    lineArray.Add(fieldBuff);
                    fieldBuff = null;
                }
            }
            return ((string[])lineArray.ToArray(typeof(string)));
        }
        public void PrintError(string message)
        {
            Console.WriteLine("# RUNTIME DYNAMIC ERR MSG");
            Console.WriteLine(message);
            Console.WriteLine("# RUNTIME DYNAMIC END MSG");
        }

    }
    public delegate void CompileUnknownScriptLineHandler(Compiler compiler, string line, string[] spaceSplitArray);
}